package com.zsc.shixun.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zsc.shixun.common.ResultCode;
import com.zsc.shixun.contant.Contant;
//import com.zsc.shixun.elasticsearch.ArticleESDao;
import com.zsc.shixun.controller.WebSocketServer;
import com.zsc.shixun.entity.Article;
import com.zsc.shixun.entity.ArticleCategories;
import com.zsc.shixun.exception.ApiException;
import com.zsc.shixun.mapper.ArticleMapper;
import com.zsc.shixun.model.article.ArticleCreateVO;
import com.zsc.shixun.model.article.ArticleMapping;
import com.zsc.shixun.model.article.ArticleUpdateVO;
import com.zsc.shixun.model.article.ArticleVO;
import com.zsc.shixun.service.IArticleCategoriesService;
import com.zsc.shixun.service.IArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsc.shixun.service.IMessageService;
import com.zsc.shixun.utils.LoginMessageUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;

/**
 * <p>
 * 文章表 服务实现类
 * </p>
 *
 * @author ZWYZY
 * @since 2020-06-06
 */
@Service
@Transactional
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements IArticleService {
    private static final Logger logger = LoggerFactory.getLogger(ArticleServiceImpl.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ArticleMapping articleMapping;

    @Autowired
    private IArticleCategoriesService articleCategoriesService;
    //    @Autowired
//    private ArticleESDao articleESDao;
    @Autowired
    private IMessageService messageService;
    @Autowired
    private LoginMessageUtils loginMessageUtils;

    @Override
    public List<ArticleVO> getData(Long id) {
        if (redisTemplate.hasKey(Contant.ARTICLE_KEY + id)) {
            return (List<ArticleVO>) redisTemplate.opsForValue().get(Contant.ARTICLE_KEY + id);
        }
        List<Article> articleList = this.list(new QueryWrapper<Article>().lambda().eq(Article::getUserId, id).orderByDesc(Article::getCreateTime));
        List<ArticleVO> articleVOS = articleMapping.entitysToVos(articleList);

        redisTemplate.opsForValue().set(Contant.ARTICLE_KEY + id, articleVOS);
        return articleVOS;
    }

    @Override
    public void update(ArticleUpdateVO articleUpdateVO) {
        Article article = new Article();

        BeanUtils.copyProperties(articleUpdateVO, article);
        try {
            this.updateById(article);
        } catch (Exception e) {
            logger.error("修改文章失败");
            throw new ApiException(ResultCode.ARTICLE_UPDATE_FAIL);
        }
        logger.info("修改文章成功");
        if (redisTemplate.hasKey(Contant.ARTICLE_KEY + article.getUserId())) {
            redisTemplate.delete(Contant.ARTICLE_KEY + article.getUserId());
        }
        if (redisTemplate.hasKey(Contant.INDEX_ARTICLE_KEY)) {
            redisTemplate.delete(Contant.INDEX_ARTICLE_KEY);
        }
    }

    @Override
    public void delete(Long id, Long uid) {
        try {
            this.removeById(id);
        } catch (Exception e) {
            logger.error("文章删除失败");
            throw new ApiException(ResultCode.ARTICLE_DELETE_FAIL);
        }
        logger.info("删除文章成功");
        if (redisTemplate.hasKey(Contant.ARTICLE_KEY + uid)) {
            redisTemplate.delete(Contant.ARTICLE_KEY + uid);
        }
        if (redisTemplate.hasKey(Contant.INDEX_ARTICLE_KEY)) {
            redisTemplate.delete(Contant.INDEX_ARTICLE_KEY);
        }
    }

    @Override
    public void insert(ArticleCreateVO articleCreateVO, Long uid) {
        Article article = new Article();
        articleCreateVO.setUserId(uid);
        BeanUtils.copyProperties(articleCreateVO, article);
        try {
            this.save(article);
        } catch (Exception e) {
            logger.error("创建文章失败");
            throw new ApiException(ResultCode.ARTICLE_INSERT_FAIL);
        }
        logger.info("创建文章成功");
        if (redisTemplate.hasKey(Contant.ARTICLE_KEY + uid)) {
            redisTemplate.delete(Contant.ARTICLE_KEY + uid);
        }

        //根据逗号分隔文章分类组成分类类型数组
        String[] strings = articleCreateVO.getCategories().split(",");
        for (int i = 0; i < strings.length; i++) {
            ArticleCategories articleCategories = articleCategoriesService.getOne(new QueryWrapper<ArticleCategories>().lambda().eq(ArticleCategories::getName, strings[i]));
            if (articleCategories != null) {
                //修改该分类类型的文章数加1
                articleCategories.setArticleNumber(articleCategories.getArticleNumber() + 1);
                articleCategoriesService.updateById(articleCategories);
                logger.info("修改文章类型成功+1");
            } else {
                //创建文章分类类型，文章数为1
                ArticleCategories categories = new ArticleCategories();
                categories.setArticleNumber(1L);
                categories.setName(strings[i]);
                categories.setUserId(uid);
                articleCategoriesService.save(categories);
                logger.info("创建文章类型成功+1");
            }
        }
        if (redisTemplate.hasKey(Contant.DATA_COMMON_KEY + uid)) {
            redisTemplate.delete(Contant.DATA_COMMON_KEY + uid);
        }
        if (redisTemplate.hasKey(Contant.DATA_ADMIN_KEY)) {
            redisTemplate.delete(Contant.DATA_ADMIN_KEY);
        }
        if (redisTemplate.hasKey(Contant.INDEX_ARTICLE_KEY)) {
            redisTemplate.delete(Contant.INDEX_ARTICLE_KEY);
        }
        if (redisTemplate.hasKey(Contant.TYPE_KEY + uid)) {
            redisTemplate.delete(Contant.TYPE_KEY + uid);
        }
    }

    @Override
    public void liking(Long id, Long uid, Long aid) {
        Article article = new Article();
        Article byId = this.getById(id);
        article.setId(id);
        article.setLikeNumber(this.getById(id).getLikeNumber() + 1);
        try {
            this.updateById(article);
        } catch (Exception e) {
            logger.error("点赞失败");
            throw new ApiException(ResultCode.ARTICLE_DELETE_FAIL);
        }
        logger.info("点赞成功");
        if (redisTemplate.hasKey(Contant.INDEX_ARTICLE_KEY)) {
            redisTemplate.delete(Contant.INDEX_ARTICLE_KEY);
        }
        if (redisTemplate.hasKey(Contant.DATA_COMMON_KEY + uid)) {
            redisTemplate.delete(Contant.DATA_COMMON_KEY + uid);
        }
        if (redisTemplate.hasKey(Contant.DATA_ADMIN_KEY)) {
            redisTemplate.delete(Contant.DATA_ADMIN_KEY);
        }
        if (redisTemplate.hasKey(Contant.ARTICLE_KEY + aid)) {
            redisTemplate.delete(Contant.ARTICLE_KEY + aid);
        }
        String message = "博主名为" + loginMessageUtils.getMessage().getLoginUser().getUsername() + "的用户点赞了你的文章：" + byId.getTitle();
        try {
            WebSocketServer.sendObjToUser(messageService.insertMessage(byId.getUserId(), loginMessageUtils.getMessage().getLoginUser().getId(), message), byId.getUserId());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void search(String keyword, int start, int size) {
//        initDatabase2ES();
//        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.matchAllQuery()
//                .add(QueryBuilders.matchPhraseQuery("name", keyword),
//                        ScoreFunctionBuilders.weightFactorFunction(100))
//                .scoreMode("sum")
//                .setMinScore(10);
//        Sort sort = new Sort(Sort.Direction.DESC, "id");
//        Pageable pageable = PageRequest.of(start, size, sort);
//        //es搜索默认第一页页码是0
//        Query searchQuery = new NativeSearchQueryBuilder()
//                .withPageable(pageable)
//                .withQuery(functionScoreQueryBuilder).build();
//        Page<Article> page = articleESDao.search(searchQuery);
////        return page.getContent();

    }
//    /** 初始化数据到es. 因为数据刚开始都在数据库中，不在es中，所以刚开始查询，
//     先看看es有没有数据，如果没有，就把数据从数据库同步到es中*/
//    private void initDatabase2ES() {
//        Pageable pageable =  PageRequest.of(0, 5);
//        Page<Article> page =articleESDao.findAll(pageable);
//        if(page.getContent().isEmpty()) {
//            List<Article> products= this.list();
//            for (Article article : products) {
//                articleESDao.save(article);
//            }
//        }
//    }


}
